package message_client

import (
	"bytes"
	"encoding/json"
	"github.com/satori/go.uuid"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

type HttpMessageClient struct {
	Endpoint string
	url      string
	client   *http.Client
}

func NewHttpMessageClient(endpoint string) *HttpMessageClient {
	var url = endpoint + "/message/send"
	client := &http.Client{Timeout: 5 * time.Second}
	return &HttpMessageClient{
		Endpoint: endpoint,
		url:      url,
		client:   client,
	}
}

func (messageClient *HttpMessageClient) SendSms(businessName string, parameter *SmsRequestParameter) (result *SendResults, err error) {
	requestParameter := buildSendParameter(businessName, parameter.Delay, parameter.SendTime, MESSAGE_TYPE_SMS)
	requestParameter.Sms = parameter
	return messageClient.doRequest(requestParameter)
}

func (messageClient *HttpMessageClient) SendAppNotification(businessName string, parameter *AppNotificationRequestParameter) (result *SendResults, err error) {
	requestParameter := buildSendParameter(businessName, parameter.Delay, parameter.SendTime, MESSAGE_TYPE_APP_NOTIFICATION)
	requestParameter.AppNotification = parameter
	return messageClient.doRequest(requestParameter)
}

func (messageClient *HttpMessageClient) SendAppTransmission(businessName string, parameter *AppTransmissionRequestParameter) (result *SendResults, err error) {
	requestParameter := buildSendParameter(businessName, parameter.Delay, parameter.SendTime, MESSAGE_TYPE_APP_TRANSMISSION)
	requestParameter.AppTransmission = parameter
	return messageClient.doRequest(requestParameter)
}

func (messageClient *HttpMessageClient) SendMail(businessName string, parameter *MailRequestParameter) (result *SendResults, err error) {
	requestParameter := buildSendParameter(businessName, parameter.Delay, parameter.SendTime, MESSAGE_TYPE_EMAIL)
	requestParameter.Email = parameter
	return messageClient.doRequest(requestParameter)
}

func (messageClient *HttpMessageClient) SendInternalMessage(businessName string, parameter *InternalMessageRequestParameter) (result *SendResults, err error) {
	requestParameter := buildSendParameter(businessName, parameter.Delay, parameter.SendTime, MESSAGE_TYPE_INTERNAL_MESSAGE)
	requestParameter.InternalMessage = parameter
	return messageClient.doRequest(requestParameter)
}

func (messageClient *HttpMessageClient) SendDingTalkMessage(businessName string, parameter *DingtalkMessageRequest) (result *SendResults, err error) {
	requestParameter := buildSendParameter(businessName, parameter.Delay, parameter.SendTime, MESSAGE_TYPE_DING_TALK_MESSAGE)
	requestParameter.DingtalkMessage = parameter
	return messageClient.doRequest(requestParameter)
}

func (messageClient *HttpMessageClient) SendExtendPlatformMessage(
	businessName string, args map[string]interface{}, delay bool, sendTime int64) (result *SendResults, err error) {

	argsBytes, _ := json.Marshal(args)
	parameter := &ExtendPlatformMessageRequest{Args: string(argsBytes)}

	requestParameter := buildSendParameter(businessName, delay, sendTime, MESSAGE_TYPE_EXTEND_PLATFORM_MESSAGE)
	requestParameter.ExtendPlatformMessage = parameter

	return messageClient.doRequest(requestParameter)
}

func (messageClient *HttpMessageClient) Send(businessName string, messageTypes []string, requestParameter *SendRequestParameter) (result *SendResults, err error) {
	requestId := uuid.NewV4().String()
	requestId = strings.ReplaceAll(requestId, "-", "")
	requestParameter.RequestId = requestId
	requestParameter.BusinessName = businessName
	requestParameter.MessageTypes = messageTypes
	return messageClient.doRequest(requestParameter)
}

func (messageClient *HttpMessageClient) doRequest(requestParameter *SendRequestParameter) (result *SendResults, err error) {

	if byteArr, err := json.Marshal(requestParameter); err == nil {
		if resp, err := messageClient.client.Post(messageClient.url, DefaultContentType, bytes.NewReader(byteArr)); err == nil {
			if response, err := processResponseBody(resp); err == nil {
				return response.ResponseBody, nil
			}
		}
	}

	return nil, err
}

func buildSendParameter(businessName string, delay bool, sendTime int64, messageType string) *SendRequestParameter {

	requestId := uuid.NewV4().String()
	requestId = strings.ReplaceAll(requestId, "-", "")

	requestParameter := &SendRequestParameter{
		RequestId:    requestId,
		BusinessName: businessName,
		MessageTypes: []string{messageType},
	}

	var isDelay = false
	if delay && sendTime > 0 {
		isDelay = true
		requestParameter.SendTime = sendTime
	}
	requestParameter.Delay = isDelay

	return requestParameter
}

func processResponseBody(resp *http.Response) (body *Response, err error) {
	defer resp.Body.Close()
	readAll, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	var response = &Response{}
	err = json.Unmarshal(readAll, response)
	return response, err
}
